/**
 @file message_def.h
 @brief Definición de los parámetros y estructuras de datos para el servicio de intercambio de mensajes.
 @date   06/11/2012
 @version v.0.9
 @author Julian Ovalle
         julianovalle@ula.ve
*/

#ifndef MESSAGE_DEF_H_
#define MESSAGE_DEF_H_

#include <inttypes.h>

//! @brief Dirección del cliente para el socket con el servicio de intercambio de mensajes.
#define CLI_SOCKET_ADDR "/tmp/xbclient"

//! @brief Dirección del servidor para el socket con el servicio de intercambio de mensajes.
#define SERVER_SOCKET_ADDR "/tmp/xbserver"

//! @brief Nombre del servicio de intercambio de mensajes en el directorio de servicios.
#define SOCKET_SERVICE_NAME "xbee"

//! @brief Tiempo máximo de espera para enviar a través del socket en milisegundos.
#define SOCKET_SEND_TIMEOUT_MSEC 100

//! @brief Tiempo máximo de espera para recibir del socket en milisegundos.
#define SOCKET_RCV_TIMEOUT_MSEC 100

//transport layer options----------------------------------
//! @brief Bit que indica que el mensaje se transmitirá en broadcast. Los receptores lo usarán para evitar enviar un ACK.
#define BROADCAST_BIT 0b10000000

//! @brief Bit para indicar al servidor que transmita el mensaje en multicast.
#define MULTICAST_BIT 0b00100000

//! @brief Bit para indicar al servidor que el comando a enviar acarrea un mensaje de respuesta.
#define RESPONSE_REQUIRED_BIT 0b00010000

//! @brief Tamaño máximo admitido de la data en tramas de capa aplicación. Valor máximo: 96bytes
#define MAX_MSG_DATA_LEN 24

//! @brief Tamaño total máximo admitido de las tramas de capa aplicación. Valor máximo: 100bytes
#define MAX_MSG_LEN  MAX_MSG_DATA_LEN+3

//! @brief Tiempo máximo de espera por el estado de una transmisión (MACk).
#define TX_STATUS_TIMEOUT 64 //prev 40 63

//! @brief Tiempo máximo en segundos de espera por la respuesta de un nodo a un comando enviado.
#define COMMAND_RESPONSE_TIMEOUT_SEC 1 // 0

//! @brief Tiempo máximo en milisegundos de espera por la respuesta de un nodo a un comando enviado.
#define COMMAND_RESPONSE_TIMEOUT_MSEC 500  // 200

//! @brief Tiempo máximo de espera en segundos por los ACKs de capa MAC para un multicast.@see msgMulticast()
#define SEND_MULTICAST_TIMEOUT_SEC 1

//! @brief Identificador de nodo especial para la transmisión en broadcast.
#define BROADCAST_ID "broadcast"

//App layer packet types-------------------------------------
//! @brief Identificador de mensaje para los acuses de recibo.
#define ACK 0x1A

#define PING 0x70

//! @brief Identificador de mensaje para señalar la finalización del servicio.
#define SERVER_EXIT 0x21

//! @brief Identificador de mensaje para solicitar la lista de nodos al servidor.
#define NODE_LIST 0x22

//! @brief Identificador de mensaje para actualizar la lista de nodos del servidor.
#define NODE_LIST_UPDATE 0x23

//-----------------------------------------------------------

struct control_msg_t {
    uint8_t options;
    uint8_t type;
    uint8_t status;
};

//! @brief Estructura para almacenar un mensaje de capa aplicación.
struct msg_t {
    uint8_t options; //!< Byte de opciones.
    uint8_t type; //!< Identificador del comando o mensaje enviado.
    uint8_t len; //!< Tamaño de la data en el mensaje.
    uint8_t data[MAX_MSG_DATA_LEN]; //!< Contenedor de la data.
    char nodeId[20]; //!< Identificador del nodo origen/destino.
};

//! @brief Estructura para almacenar un mensaje en la cola de mensajes correspondiente
struct msg_buf {
    long mtype;
    struct msg_t msg;
};

//! @brief Estructura para almacenar un mensaje de control en la cola de mensajes correspondiente
struct control_msg_buf {
    long mtype;
    struct control_msg_t cmsg;
};

//! @brief Estructura para almacenar la lista de destinatarios para un mensaje multicast.
typedef struct {
    uint8_t size; //!< Número de elementos.
    char **id_list; //!< Apuntador a los identificadores de los nodos.
} dest_list_t;

//! @brief Estructura para almacenar un comando definido por el usuario y sus argumentos.
typedef struct {

    uint8_t opt; //!< Byte de opciones del comando. Viajará en el byte de opciones de un mensaje.
    uint8_t command; //!< Byte identificador del comando. Definido por el usuario.

    uint8_t byte_num; //!< Cantidad de argumentos enteros de 8 bits.
    uint8_t short_num; //!< Cantidad de argumentos enteros de 16 bits.
    uint8_t int_num; //!< Cantidad de argumentos de tipo entero estándar.
    uint8_t float_num; //!< Cantidad de argumentos de tipo flotante.
    uint8_t double_num; //!< Cantidad de argumentos de flotantes de doble precisión.

    uint8_t *byte_args; //!< Contenedor de los argumentos enteros de 8 bits.
    short int *short_args; //!< Contenedor de los argumentos enteros de 16 bits.
    int *int_args; //!< Contenedor de los argumentos enteros estándar.
    float *float_args; //!< Contenedor de los argumentos enteros de tipo flotante.
    double *dbl_args; //!< Contenedor de los argumentos enteros de tipo flotante de doble precisión.

    char *destination; //!< Identificador del nodo destino para unicast o broadcast.
    dest_list_t *destination_list; //!< Lista de destinatarios para multicast. @see dest_list_t

}command_arg_t;

#endif /* MESSAGE_DEF_H_ */
